package audio

import (
	"crypto/hmac"
	"crypto/sha1"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"gxcvu-ai/pkg/chat"
	"io"
	"net/http"
	"net/url"
	"sort"
	"strings"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
)

const (
	AccessKeyId      = "LTAI5tEGHRrHCybj9cbVMTQC"
	AccessSecret     = "sD0LebHcr7MntyL1cxrUiTSnbsxWWY"
	Action           = "CreateToken"
	Version          = "2019-02-28"
	RegionId         = "cn-shanghai"
	SignatureMethod  = "HMAC-SHA1"
	SignatureVersion = "1.0"
)

type Aliyun struct {
}

type Param struct {
	Key   string
	Value string
}

type AilyunSignatureReponse struct {
	Errmsg string `json:"ErrMsg"`
	Token  struct {
		UserId     string `json:"UserId"`
		Id         string `json:"Id"`
		ExpireTime string `json:"ExpireTime"`
	}
}

func HmacSHA1(key string, data string) string {
	mac := hmac.New(sha1.New, []byte(key))
	mac.Write([]byte(data))
	return base64.StdEncoding.EncodeToString(mac.Sum(nil))
}

func sortMapByKey(params map[string]string) []Param {
	// 创建一个Param类型的切片
	var paramsSlice []Param

	// 遍历map，将键值对添加到切片中
	for k, v := range params {
		paramsSlice = append(paramsSlice, Param{k, v})
	}

	// 使用sort包中的Sort函数对切片进行排序
	sort.Slice(paramsSlice, func(i, j int) bool {
		return paramsSlice[i].Key < paramsSlice[j].Key
	})

	return paramsSlice
}

func getToken() string {
	const _url = "https://nls-meta.cn-shanghai.aliyuncs.com/"

	body := map[string]string{
		"AccessKeyId":      AccessKeyId,
		"Action":           Action,
		"Version":          Version,
		"RegionId":         RegionId,
		"SignatureMethod":  SignatureMethod,
		"SignatureVersion": SignatureVersion,
		"Timestamp":        time.Now().UTC().Format("2006-01-02T15:04:05Z"),
		"SignatureNonce":   uuid.New().String(),
		"Format":           "JSON",
	}

	sortBody := sortMapByKey(body)

	// 对编码后的body进行url编码
	var strBuilder strings.Builder
	for _, param := range sortBody {
		strBuilder.WriteString(param.Key)
		strBuilder.WriteString("=")
		strBuilder.WriteString(url.QueryEscape(param.Value))
		strBuilder.WriteString("&")
	}
	origin_body := strBuilder.String()
	fmt.Println(origin_body)
	origin_body = strings.TrimSuffix(origin_body, "&")

	// 构造请求头
	strBuilder.Reset()
	strBuilder.WriteString("GET")
	strBuilder.WriteString("&")
	strBuilder.WriteString(url.PathEscape("/"))
	strBuilder.WriteString("&")
	strBuilder.WriteString(url.QueryEscape(origin_body))
	signToString := strBuilder.String()
	// fmt.Println(signToString)
	// fmt.Println()

	signature := HmacSHA1(AccessSecret+"&", signToString)
	signature = url.QueryEscape(signature)
	// fmt.Println(signature)
	// fmt.Println()

	signature = "Signature=" + signature + "&" + origin_body
	// fmt.Println(signature)
	// fmt.Println()

	req, err := http.NewRequest("GET", _url+"?"+signature, strings.NewReader(""))
	if err != nil {
		fmt.Println(err)
	}
	defer req.Body.Close()
	response_body, err := http.DefaultClient.Do(req)
	if err != nil {
		fmt.Println(err)
	}
	defer response_body.Body.Close()
	resp, _ := io.ReadAll(response_body.Body)
	var responseJson AilyunSignatureReponse
	json.Unmarshal([]byte(resp), &responseJson)

	return responseJson.Token.Id
}

type AliyunTTSRequest struct {
	Header struct {
		Appkey    string `json:"appkey"`
		MessageId string `json:"message_id"`
		TaskId    string `json:"task_id"`
		Namespace string `json:"namespace"`
		Name      string `json:"name"`
	}
	Payload struct {
		Text string `json:text`
	}
}

func (e Aliyun) NewAudio(message chat.Message, c *gin.Context) {
	//todo
	// token := getToken()
	// _url := "wss://nls-gateway-cn-shanghai.aliyuncs.com/ws/v1?token=" + token
	// // 创建一个WS Client
	// u := url.URL{Scheme: "wss", Host: _url, Path: "/"}
	// client, _, err := websocket.Dial(u.String(), nil)
	// if err != nil {
	// 	fmt.Println(err)
	// }
	// defer client.Close()

	// go func() {
	// 	defer close(done)
	// 	for {
	// 		mt, message, err := c.ReadMessage()
	// 		if err != nil {
	// 			log.Println("read:", err)
	// 			return
	// 		}
	// 		log.Printf("recv: %s, type: %s", message, websocket.FormatMessageType(mt))
	// 	}
	// }()

	// ticker := time.NewTicker(time.Second)
	// defer ticker.Stop()

}
